home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’90 / Validate Text Entry / NumValFilter.f < prev    next >
Encoding:
Text File  |  1990-06-15  |  10.1 KB  |  323 lines  |  [TEXT/MPS ]

  1. !!M Inlines.f
  2. c!!S USER
  3.  
  4.  
  5. C
  6. C  This is the filter proc for modal dialog which supports the validation
  7. C  of text entry.
  8. C
  9. C  Written by Jeff E Mandel MD MS 1990
  10. C
  11.  
  12.     logical*1 function NumValFilter ( theDialog , theEvent , itemHit )
  13.     
  14.     implicit none
  15.     
  16. !!SETC USINGINCLUDES = .FALSE.
  17.     Include    'TYPES.F'
  18.     Include    'DIALOGS.F'
  19.     include 'EVENTS.F'
  20.     include 'SANE.F'
  21.  
  22.     include 'format.inc'
  23.     
  24.     record /decimal/ d
  25.     record /decform/ f
  26.     integer*1 r
  27.     extended x
  28.     string*255 s , s1
  29.     logical*1 validprefix
  30.     integer*2 index , activeItem
  31.     
  32.     Record /DialogRecord/ theDialog
  33.     Record /EventRecord/  theEvent
  34.     pointer /resourcePtrType/ formatHandle
  35.     structure /stringPointer/
  36.         pointer /integer*1/ ptr
  37.     end structure
  38.     integer*1 lenByte
  39.     integer*2 theKeys(0:7)
  40.     
  41.     logical good
  42.     common /numValFilt/ good
  43.     
  44.     pointer /stringPointer/ stringHandle
  45.  
  46.     record /Rect/ box , defaultBox
  47.     integer*4 itemHandle , PrivateEvent
  48.     integer*2 ItemType
  49.     
  50.     integer*2 ptrue
  51.  
  52.     integer*4 offset , len1 , j , theNum , ptr1 , sourcePtr
  53.     integer*2 itemHit , i , theField , Drag
  54.     character*1 theChar
  55.     character*256 debugChar
  56.     logical validate
  57.     
  58.     DATA    ptrue / 1 /
  59.     
  60.     if ( theEvent.what .eq. keyDown .or. theEvent.what .eq. autoKey ) then
  61.         theNum = jiand ( theEvent.message , charCodeMask )
  62.         formatHandle = theDialog.window.refCon
  63. C
  64. C  If the dialog has no format resource, handle return and enter but do nothing else
  65. C
  66.         if ( formatHandle .eq. 0 ) then
  67.             if ( theNum .eq. 3 .or. theNum .eq. 13 ) then
  68.                 NumValFilter = ptrue
  69.                 itemHit = theDialog.aDefItem
  70.             else
  71.                 NumValFilter = .false.
  72.             end if
  73.             go to 20
  74.         end if
  75.  
  76. C
  77. C  Figure out which item in the format resource handles the current item. The
  78. C  current item is recovered from editField
  79. C
  80.  
  81.         validate = .false.
  82.         theField = theDialog.editField+1
  83.         do i = 1 , formatHandle^.Ptr^.count
  84.             if (formatHandle^.Ptr^.format(i).theItem .eq. theField) then
  85.                 activeItem = i
  86.                 validate = .true.
  87.                 leave
  88.             end if
  89.         end do
  90.  
  91.         if ( (theNum .eq. 3 .or. theNum .eq. 13) .and. ( good .or.
  92.     1        (theDialog.aDefItem .ne. formatHandle^.Ptr^.okItem) )) then
  93.                 NumValFilter = ptrue
  94.                 itemHit = theDialog.aDefItem
  95.         else if ( .not. validate ) then
  96.             NumValFilter = .false.
  97.         else if ( theNum .eq. 9 ) then
  98. C
  99. C  This is tricky. If we have the text partieally selected, and the value is bad,
  100. C  and the user hits the tab key, we need to foce a redraw of the invalidation, as
  101. C  otherwise the dialog manager will have redrawn the selected text in the undimmed
  102. C  state, confusing the user.
  103. C
  104.             if ( ((theDialog.textH.TEH^.TEP^.selStart .ne.
  105.     1               theDialog.textH.TEH^.TEP^.selEnd) .or.
  106.     2              (theDialog.textH.TEH^.TEP^.nLines .gt. 1 ) ) .and.
  107.     3               formatHandle^.Ptr^.format(activeItem).badVal ) then
  108.                 call GetDItem ( theDialog , %val(theField) , ItemType , itemHandle , box )
  109.                 call InvalRect ( box )
  110.             end if
  111.             NumValFilter = .false.
  112.         else if ( theNum .ge. 28 .and. theNum .le. 31 ) then
  113. C
  114. C  ASCII codes we don't handle
  115. C
  116.             NumValFilter = .false.
  117.         else if ( formatHandle^.Ptr^.format(activeItem).theType .eq. TextFormat ) then
  118. C
  119. C  TextFormat - the only criterion for validation is the number of characters. If a valid
  120. C  key is hit, increment the count by one, unless the key is delete. The only trick is if
  121. C  there is a selection, account for the fact that multiple characters will vanish
  122. C
  123.  
  124.             call GetDItem ( %ref(theDialog) , %val(theField) , ItemType , itemHandle , box )
  125.             call GetIText ( %val(itemHandle) , %ref(s) )
  126.             len1 = theDialog.textH.TEH^.TEP^.selEnd - theDialog.textH.TEH^.TEP^.selStart
  127.             index = len(s)
  128.             if ( theNum .eq. 8 ) then
  129.                 if ( len1 .eq. 0 .and. theDialog.textH.TEH^.TEP^.selStart .ne. 0 ) len1 = 1
  130.                 index = index - len1
  131.             else
  132.                 index = index - len1 + 1
  133.             end if
  134.             x = QFLOAT ( index ) 
  135.             call GetDItem ( %ref(theDialog) , %val(formatHandle^.Ptr^.defaultItem)
  136.     1                        , ItemType , itemHandle , defaultBox )
  137.             if (     (x .lt. formatHandle^.Ptr^.format(activeItem).minVal) 
  138.     1           .or. (x .gt. formatHandle^.Ptr^.format(activeItem).maxVal) ) then
  139.                     formatHandle^.Ptr^.format(activeItem).badVal = .true.
  140.                     call InvalRect ( box )
  141.                     call InvalRect ( defaultBox )
  142.                     good = .false.
  143.             else if  ( formatHandle^.Ptr^.format(activeItem).badVal ) then
  144.                 formatHandle^.Ptr^.format(activeItem).badVal = .false.
  145.                 call InvalRect ( box )
  146.                 call InvalRect ( defaultBox )
  147.             end if
  148.             NumValFilter = .false.
  149.         else if ( (formatHandle^.Ptr^.format(activeItem).theType .eq. IntegerFormat) .and. theNum .eq. 46 ) then
  150. C
  151. C  Ignore the decimal point in integer fields
  152. C
  153.             NumValFilter = .false.
  154.             theEvent.what = NullEvent
  155.         else if ( theNum .eq. 45 .or. theNum .eq. 46 .or. theNum .eq. 8
  156.     1                 .or. (theNum .ge. 48 .and. theNum .le. 57)) then
  157.  
  158. C  We have a number which must be incorporated into the string. Since the user
  159. C  could have moved the insertion point, or even dragged over any or all of the
  160. C  item's contents, we use the toolbox Munger (IM-I pp468-9) to properly kludge
  161. C  the string. Note that the delete key must be treated as a special case.
  162.  
  163.             call GetDItem ( %ref(theDialog) , %val(theField) , ItemType , itemHandle , box )
  164.             call GetIText ( %val(itemHandle) , %ref(s) )
  165.             stringHandle = NewString ( %ref(s) )
  166.             offset = theDialog.textH.TEH^.TEP^.selStart + 1
  167.             len1 = theDialog.textH.TEH^.TEP^.selEnd - theDialog.textH.TEH^.TEP^.selStart
  168.             if ( theNum .eq. 8 
  169.     1          .and. .not.(theDialog.textH.TEH^.TEP^.selStart .eq. 0 
  170.     2          .and.    len1 .eq. 0) ) then
  171.                 if ( len1 .eq. 0 ) then
  172.                     len1 = 1
  173.                     offset = offset - 1
  174.                 end if
  175.                 ptr1 = NewPtr ( %val(len1) )
  176.                 sourcePtr = stringHandle^.ptr
  177.                 sourcePtr = sourcePtr + offset
  178.                 call BlockMove ( %val(sourcePtr) , %val(ptr1) , %val(len1) )
  179.                 j = Munger ( %val(stringHandle) , %val(offset) , %val(ptr1) ,
  180.     1                 %val(len1) , %ref(0) , %val(0) )
  181.                 call DisposPtr ( %val(ptr1) )
  182.             else
  183.                 theChar =  char (theNum)
  184.                 j = Munger ( %val(stringHandle) , %val(offset) , %val(0)
  185.     1                     , %val(len1) ,    %ref(theChar) , %val(1) )
  186.             end if
  187.             lenByte = GetHandleSize ( %val(stringHandle) ) - 1
  188.             stringHandle^.ptr^ = lenByte
  189.             index = 1
  190. C
  191. C  Convert the string to a DECFORM to see if it is valid. If not, reject the keystroke
  192. C
  193.  
  194.             call STR2DEC ( %val(stringHandle^.ptr) , index , d , validprefix)
  195.             call DisposHandle ( %val(stringHandle) )
  196.             if ( .not. validprefix ) then
  197.                 NumValFilter = .false.
  198.                 theEvent.what = NullEvent
  199.             else
  200. C
  201. C  We have a number! See if it is in the valid range
  202. C
  203.  
  204.                 x = DEC2NUM(d)
  205.                 call GetDItem ( %ref(theDialog) , %val(formatHandle^.Ptr^.defaultItem)
  206.     1                            , ItemType , itemHandle , defaultBox )
  207.                 if (     (x .lt. formatHandle^.Ptr^.format(activeItem).minVal) .or.
  208.     1                    (x .gt. formatHandle^.Ptr^.format(activeItem).maxVal) ) then
  209. C
  210. C  It is not. Set the badVal flag for the field, and invalRect the cooperating
  211. C  userItems that handle graying.
  212. C
  213.                     formatHandle^.Ptr^.format(activeItem).badVal = .true.
  214.                     call InvalRect ( box )
  215.                     call InvalRect ( defaultBox )
  216.                     good = .false.
  217.                 else if  ( formatHandle^.Ptr^.format(activeItem).badVal ) then
  218. C
  219. C  The inverse
  220. C
  221.                     formatHandle^.Ptr^.format(activeItem).badVal = .false.
  222.                     call InvalRect ( box )
  223.                     call InvalRect ( defaultBox )
  224.                 end if
  225.  
  226.                 NumValFilter = .false.
  227.             end if
  228.         else
  229.             NumValFilter = .false.
  230.             theEvent.what = NullEvent
  231.         end if
  232.  
  233.     else if ( theEvent.what .eq. mouseDown ) then
  234.         formatHandle = theDialog.window.refCon
  235.         if ( formatHandle .ne. 0  .and. itemHit .gt. 0 ) then
  236.             theField = theDialog.editField+1
  237.             do i = 1 , formatHandle^.Ptr^.count
  238. C
  239. C  Similar to the tabbing problem described above, except we have to search to find
  240. C  the correct item
  241. C
  242.                 if (formatHandle^.Ptr^.format(i).theItem .eq. theField) then
  243.                     if ( ((theDialog.textH.TEH^.TEP^.selStart .ne. 
  244.     1                       theDialog.textH.TEH^.TEP^.selEnd) .or.
  245.     2                        (theDialog.textH.TEH^.TEP^.nLines .gt. 1 ) ) .and.
  246.     3                        formatHandle^.Ptr^.format(activeItem).badVal ) then
  247.                         call GetDItem ( theDialog , %val(theField) , ItemType , itemHandle , box )
  248.                         call InvalRect ( box )
  249.                     end if
  250.                     leave
  251.                 end if
  252.             end do
  253.         end if
  254.         NumValFilter = .false.
  255.     else if ( theEvent.what .eq. NullEvent ) then
  256.         formatHandle = theDialog.window.refCon
  257.         if ( formatHandle .eq. 0 ) then
  258.             NumValFilter = .false.
  259.             go to 20
  260.         end if
  261. C
  262. C  Handle the pressing of the option key, which displays the vaidation criteria in
  263. C  the cooperating staticText item
  264. C
  265.         call GetKeys ( theKeys )
  266.         if ( bitest( theKeys(3) , 2 ) .and. origField ) then
  267.             theField = theDialog.editField+1
  268.             do i = 1 , formatHandle^.Ptr^.count
  269.                 if (formatHandle^.Ptr^.format(i).theItem .eq. theField) then
  270.                     call GetDItem ( theDialog , %val(formatHandle^.Ptr^.format(i).theLabel)
  271.     1                                , ItemType , origFieldHandle , box )
  272.                     call GetIText ( %val(origFieldHandle) , %ref(origFieldText) )
  273.                     if ( formatHandle^.Ptr^.format(i).theType .eq. IntegerFormat ) then
  274.                         r = TOWARDZERO
  275.                         f.style = FIXEDDECIMAL
  276.                         f.digits = 0
  277.                         call SETROUND(r)
  278.                         x = formatHandle^.Ptr^.format(i).minVal
  279.                         call NUM2STR(f,x,%ref(s))
  280.                         x = formatHandle^.Ptr^.format(i).maxVal
  281.                         call NUM2STR(f,x,%ref(s1))
  282.                         s = s // ' ≤ value ≤ ' // s1
  283.                     else if ( formatHandle^.Ptr^.format(i).theType .eq. RealFormat ) then
  284.                         r = TONEAREST
  285.                         f.style = FIXEDDECIMAL
  286.                         f.digits = 1
  287.                         call SETROUND(r)
  288.                         x = formatHandle^.Ptr^.format(i).minVal
  289.                         call NUM2STR(f,x,%ref(s))
  290.                         x = formatHandle^.Ptr^.format(i).maxVal
  291.                         call NUM2STR(f,x,%ref(s1))
  292.                         s = s // ' ≤ value ≤ ' // s1
  293.                     else if ( formatHandle^.Ptr^.format(i).theType .eq. TextFormat ) then
  294.                         r = TOWARDZERO
  295.                         f.style = FIXEDDECIMAL
  296.                         f.digits = 0
  297.                         call SETROUND(r)
  298.                         x = formatHandle^.Ptr^.format(i).minVal
  299.                         call NUM2STR(f,x,%ref(s))
  300.                         x = formatHandle^.Ptr^.format(i).maxVal
  301.                         call NUM2STR(f,x,%ref(s1))
  302.                         s = s // ' ≤ # chars ≤ ' // s1
  303.                     end if
  304.                     call SetIText ( %val(origFieldHandle) , %ref(s) )
  305.                     origField = .false.
  306.                     leave
  307.                 end if
  308.             end do
  309.         else if ( .not. bitest( theKeys(3) , 2 ) .and. .not. origField ) then
  310. C
  311. C  Restore on option key up
  312. C
  313.             call SetIText ( %val(origFieldHandle) , %ref(origFieldText) )
  314.             origField = .true.
  315.         end if
  316.         NumValFilter = .false.
  317.     else
  318.         NumValFilter = .false.
  319.     end if
  320. 20    return
  321.     
  322.     end
  323.